package net.niufei.study.cpatterns.future;

public class FutureResult implements Result {
	
	private Result result;
	private volatile boolean completed = false;
	private FutureListener[] listeners = new FutureListener[0];
	
	
	@Override
	public synchronized Object getResultValue() {
		try {
			while (!completed) {
				wait();
			}
		} catch (InterruptedException e) {
		}
		return result == null ? null : result.getResultValue();
	}

	
	public void setResult(Result result) {
		if(!completed) {
			synchronized (this) {
				if(!completed) {
					this.result = result;
					completed = true;
					notifyAll();	
					dispatchFutureComplete();
				}
			}
		}
	}
	
	
	private void dispatchFutureComplete() {
		for (FutureListener listener : listeners) {
			listener.futureCompleted();
		}
	}
	
	
	
	public void addListener(FutureListener listener) {
		if(!completed && listener != null) {
			synchronized (this) {
				//double check
				if(!completed) {
					int length = listeners.length;
					FutureListener[] temp = new FutureListener[length+1];
					System.arraycopy(listeners, 0, temp, 0, length);
					temp[length] = listener;
					listeners = temp;
				}
			}
		}
	}
	
	
	
	public void removeListener(FutureListener listener) {
		if(!completed && listener != null) {
			synchronized (this) {
				if(!completed) {
					int length = listeners.length;
					for(int i = 0; i < length; i++) {
						if(listener == listeners[i]) {
							FutureListener[] temp = new FutureListener[length-1];
							System.arraycopy(listeners, 0, temp, 0, i);
							System.arraycopy(listeners, i+1, temp, i, length-i-1);
							listeners = temp;
							break;
						}
					}
				}
			}
		}
	}
}
